#include <iostream>

namespace concept {

    /*
     //works with alternative 1 and 2
    template <typename Type, typename Concept>
        struct is
        {
            typedef char no;
            typedef char (&yes)[2];

            template <int N>
                struct hint { };

            template <typename T>
                static yes test(T*, hint<sizeof(typename Concept::template apply<T>)>*);

            template <typename T>
                 static no test(...);

            static const bool value = (sizeof(test<Type>(0,0))==sizeof(yes));
        };
        */

    //works with alternative 0
    template <typename Type, typename Concept>
        struct is
        {
            static const bool value = (sizeof(Concept::template test<Type>(0))==sizeof(typename Concept::yes));
        };
}

template <typename Class, typename Type, Type Class::* Pointer>
    struct member
    {
        typedef int    type;
    };

//the Serializable Concept
/*
//alternative 0
*/
struct Saveable
{
    typedef char (&yes)[2];
    typedef char no;

    template <typename T>
        static yes test(member<T, void(), &T::save>* c0 = 0,
                        member<T, void(), &T::load> * c1 =0);

    template <typename T>
        static no  test(...);

};

#define DEFINE_CONCEPT(NAME, CONSTRAINTS)           \
    template <typename Type>                        \
        struct NAME                                 \
        {                                           \
            typedef char (&yes)[2];                 \
            typedef char no;                        \
                                                    \
            template <typename T>                   \
                static yes test CONSTRAINTS;        \
                                                    \
            template <typename T>                   \
                static no  test(...);               \
            static const bool value = (sizeof(test<Type>(0))==sizeof(yes)); \
        };

//#define HAS_MEMBER(TYPE, PTR)           \

DEFINE_CONCEPT(Urgable,(
        member<T, void(), &T::save>* c0 = 0,
        member<T, void(), &T::load>* c1 = 0))
/*
//alternative 1
struct Saveable
{
    template <  typename T,
                typename Constraint0 = member<T, void(), &T::save>,
                typename Constraint1 = member<T, void(), &T::load> >
        struct apply
        { };
};

//alternative 2
struct Saveable
{
    template <  typename T,
                typename member<T, void(), &T::save>::type = 0,
                typename member<T, void(), &T::load>::type = 0>
        struct apply
        { };
};
*/

//test structs
struct test_a{ void save(){} void load(){} };
struct test_b{ void save(){} };

int main()
{
    std::cout << Urgable<test_b>::value << std::endl;
    /*std::cout << ((concept::is<test_a, Saveable>::value) ? "true" : "false") << std::endl
              << ((concept::is<test_b, Saveable>::value) ? "true" : "false") << std::endl
              << ((concept::is<int, Saveable>::value) ?    "true" : "false") << std::endl;
              */
}
